<?php
/**
 * author : v_gaobingbing@duxiaoman.com
 * createTime : 2021/8/19 1:13 下午
 * description : 华为云obs
 */

namespace SweetSunnyFlower\LaravelFilesystemObs;


use Obs\ObsClient;
use SweetSunnyFlower\LaravelFilesystemObs\exceptions\InvalidArgumentException;

/**
 * Class Obs
 *
 * @package SweetSunnyFlower\LaravelFilesystemObs
 */
class Obs
{

    protected $appKey;

    protected $appSecret;

    protected $endpoint;

    protected $bucket = '';

    protected $obsClient;

    const SUCCESS = 200;

    const FAILED = 501;

    public function __construct($config = [])
    {
        $this->setConfig($config);

        $this->obsClient = ObsClient::factory([
            'key' => $this->getAppKey(),
            'secret' => $this->getAppSecret(),
            'endpoint' => $this->getEndpoint(),
            'socket_timeout' => 30,
            'connect_timeout' => 10,
        ]);
    }

    public function setBucket($bucketName)
    {
        $this->bucket = $bucketName;

        return $this;
    }

    /**
     *  'obs' => [
     * 'driver'     => 'obs',
     * 'app_key' => env('OBS_APP_KEY', 'xxxxxxxxxxxxxxxx'),
     * 'app_secret' => env('OBS_SECRET_KEY', 'xxxxxxxxxxxxxxxx'),
     * 'bucket'     => env('OBS_BUCKET', 'test'),
     * 'endpoint'     => env('OBS_ENDPOINT', 'xxx.clouddn.com'), // or host: https://xxxx.clouddn.com
     * ],
     */
    public function setConfig($config)
    {
        $this->appKey = $config['app_key'];
        $this->appSecret = $config['app_secret'];
        $this->endpoint = $config['endpoint'];
        $this->bucket = $config['bucket'];

        return $this;
    }

    /**
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function getAppKey()
    {
        if (!$this->appKey) {
            throw new InvalidArgumentException('appKey');
        }

        return $this->appKey;
    }

    public function getAppSecret()
    {
        if (!$this->appSecret) {
            throw new InvalidArgumentException('appSecret');
        }

        return $this->appSecret;
    }

    public function getBucket()
    {
        if (!$this->bucket) {
            throw new InvalidArgumentException('bucket');
        }

        return $this->bucket;
    }

    public function getEndpoint()
    {
        if (!$this->endpoint) {
            throw new InvalidArgumentException('endpoint');
        }

        return $this->endpoint;
    }

    public function __call($function, $arguments)
    {
        try {
            return call_user_func_array(array($this, $function), $arguments);
        } catch (\Exception $exception) {
            return array(
                'HttpStatusCode' => self::FAILED,
                'Reason' => $exception->getMessage(),
            );
        }
    }

    private function createBucket(string $bucketName = '')
    {
        return $this->obsClient->createBucket([
            'Bucket' => $bucketName ?: $this->getBucket(),
        ]);
    }

    private function deleteBucket(string $bucketName = '')
    {
        return $this->obsClient->deleteBucket([
            'Bucket' => $bucketName ?: $this->getBucket(),
        ]);
    }

    private function listBuckets()
    {
        return $this->obsClient->listBuckets();
    }

    private function listObjects(string $bucketName = '')
    {
        return $this->obsClient->listObjects(array(
            'Bucket' => $bucketName ?: $this->getBucket(),
            'Delimiter' => '',
            'Marker' => '',
            'MaxKeys' => '',
            'Prefix' => '',
        ));
    }

    private function deleteObject(string $objectKey, string $bucketName = '')
    {
        return $this->obsClient->deleteObject(array(
            'Bucket' => $bucketName ? : $this->getBucket(),
            'Key' => $objectKey,
            'VersionId' => '',
        ));
    }

    private function putObject(
        string $objectKey,
        string $contentType,
        $sourceFile,
        string $bucketName = '',
        $meta = []
    ) {
        return $this->obsClient->putObject(array(
            'Bucket' => $bucketName ? : $this->getBucket(),
            'Key' => $objectKey,
            'Metadata' => $meta,
            // 'Body'=>'msg to put',
            'ContentType' => $contentType,
            'SourceFile' => $sourceFile,
        ));
    }

    private function getObject($objectKey, $alias,  $bucketName = '')
    {
        return $this->obsClient->getObject(array(
            'Bucket' => $bucketName ? : $this->getBucket(),
            'Key' => $objectKey,
            'SaveAsFile' => $alias,
        ));
    }

}